package com.lfk.justwetools.Utils;

import ohos.agp.components.element.Element;
import ohos.agp.components.element.PixelMapElement;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.Rect;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.media.image.ImagePacker;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.AlphaType;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.ScaleMode;
import ohos.media.image.common.Size;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;

/**
 * 图片处理工具类
 *
 * @author liufengkai
 */
public class PicUtils {

    /**
     * 将Bitmap转换成字符串
     *
     * @param pixelMap 传入图片的pixelMap
     * @return String
     */
    public static String bitmapToString(PixelMap pixelMap) {
        String bitmapString = null;
        ByteArrayOutputStream bStream = new ByteArrayOutputStream();
        ImagePacker imagePacker = ImagePacker.create();
        ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
        packingOptions.format = "image/png";
        packingOptions.quality = 100;
        boolean result = imagePacker.initializePacking(bStream, packingOptions);
        if (result) {
            result = imagePacker.addImage(pixelMap);
            if (result) {
                imagePacker.finalizePacking();
                byte[] bytes = bStream.toByteArray();
                bitmapString = Base64.getEncoder().encodeToString(bytes);
                return bitmapString;
            }
        }
        return null;
    }

    /**
     * 将字符串转换成Bitmap类型
     *
     * @param string 传入图片转出的字符串
     * @return PixelMap
     */
    public static PixelMap stringToBitmap(String string) {
        PixelMap pixelMap = null;
        try {
            byte[] bitmapArray = Base64.getDecoder().decode(string);
            ImageSource.SourceOptions srcOpts = new ImageSource.SourceOptions();
            srcOpts.formatHint = "image/png";
            ImageSource imageSource = ImageSource.create(bitmapArray, 0, bitmapArray.length, srcOpts);
            pixelMap = imageSource.createPixelmap(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return pixelMap;
    }


    /**
     * 合成图层
     *
     * @param background 背景
     * @param foreground 前景
     * @return PixelMap
     */
    private PixelMap toConformBitmap(PixelMap background, PixelMap foreground) {
        if (background == null || foreground == null) {
            return null;
        }
        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.pixelFormat = PixelFormat.ARGB_8888;
        options.size = background.getImageInfo().size;
        options.editable = true;
        PixelMap bitmap = PixelMap.create(options);
        Canvas cv = new Canvas(new Texture(bitmap));
        cv.drawPixelMapHolder(new PixelMapHolder(background), 0, 0, new Paint());
        cv.drawPixelMapHolder(new PixelMapHolder(foreground), 0, 0, new Paint());
        return bitmap;
    }


    public static void compressImageToStream(PixelMap pixelMap, String format, int quality, OutputStream outputStream) {
        ImagePacker imagePacker = ImagePacker.create();
        ImagePacker.PackingOptions packingOptions = new ImagePacker.PackingOptions();
        packingOptions.format = format;
        packingOptions.quality = quality;
        imagePacker.initializePacking(outputStream, packingOptions);
        imagePacker.addImage(pixelMap);
        imagePacker.finalizePacking();
    }

    private static PixelMap decodeStreamToBitmap(InputStream is, String format, ImageSource.DecodingOptions opts) {
        ImageSource.SourceOptions srcOpts = null;
        if (format != null) {
            srcOpts = new ImageSource.SourceOptions();
            srcOpts.formatHint = format;
        }
        ImageSource imageSource = ImageSource.create(is, srcOpts);
        return imageSource.createPixelmap(opts);
    }
    /**
     * 自动压缩图片
     *
     * @param image 传入图片bitmap
     * @return bitmap
     */
    public static PixelMap compressImage(PixelMap image) {
        ByteArrayOutputStream baoS = new ByteArrayOutputStream();
        // 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baoS中
        int options = 100;
        // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
        do {
            baoS.reset();
            compressImageToStream(image, "image/jpeg", options, baoS);
            options -= 10;
        } while (baoS.toByteArray().length / 1024 > 100);

        // 把压缩后的数据baos存放到ByteArrayInputStream中
        ByteArrayInputStream isBm = new ByteArrayInputStream(baoS.toByteArray());
        // 把ByteArrayInputStream数据生成图片
        return decodeStreamToBitmap(isBm, "image/jpeg", null);
    }

    /**
     * 指定压缩的质量压缩图片
     *
     * @param image   传入图片的Bitmap
     * @param options 压缩图片质量
     * @return bitmap
     */
    public static PixelMap compressImage(PixelMap image, int options) {
        ByteArrayOutputStream baoS = new ByteArrayOutputStream();
        compressImageToStream(image, "image/jpeg", options, baoS);
        ByteArrayInputStream isBm = new ByteArrayInputStream(baoS.toByteArray());
        return decodeStreamToBitmap(isBm, "image/jpeg", null);
    }

    /**
     * 按照比例进行缩放
     *
     * @param image  传入的Bitmap
     * @param width  传入的宽度
     * @param height 传入的高度
     * @return PixelMap
     */
    private static PixelMap compressWithMeasure(PixelMap image, int width, int height) {
        ByteArrayOutputStream baoS = new ByteArrayOutputStream();
        compressImageToStream(image, "image/jpeg", 100, baoS);
        // 判断如果图片大于1M,进行压缩避免在生成图片（ImageSource.decodeStream）时溢出
        if (baoS.toByteArray().length / 1024 > 1024) {
            // 这里压缩50%，把压缩后的数据存放到baoS中
            baoS.reset();
            compressImageToStream(image, "image/jpeg", 50, baoS);
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baoS.toByteArray());
        PixelMap bitmap = decodeStreamToBitmap(isBm, "image/jpeg", null);
        int w = bitmap.getImageInfo().size.width;
        int h = bitmap.getImageInfo().size.height;
        // 缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        // be = 1表示不缩放
        int be = 1;
        if (w > h && w > width) {
            // 如果宽度大的话根据宽度固定大小缩放
            be = w / width;
        } else if (w < h && h > height) {
            // 如果高度高的话根据宽度固定大小缩放
            be = h / height;
        }
        if (be <= 0)
            be = 1;
        // 设置缩放比例
        ImageSource.DecodingOptions newOpts = new ImageSource.DecodingOptions();
        newOpts.sampleSize = be;
        isBm = new ByteArrayInputStream(baoS.toByteArray());
        bitmap = decodeStreamToBitmap(isBm, "image/jpeg", newOpts);
        // 压缩好比例大小后再进行质量压缩
        return compressImage(bitmap);
    }

    /**
     * 按照原比例进行缩放
     *
     * @param image
     * @return PixelMap
     */
    public static PixelMap compressWithMeasure(PixelMap image) {
        return compressWithMeasure(image, image.getImageInfo().size.width, image.getImageInfo().size.height);
    }

    /**
     * 获取网络上的图片
     *
     * @param url
     * @return
     */
    public static PixelMap getHttpBitmap(String url) {
        URL myFileURL;
        PixelMap bitmap = null;
        try {
            myFileURL = new URL(url);

            // 获得连接
            HttpURLConnection conn = (HttpURLConnection) myFileURL.openConnection();

            conn.setConnectTimeout(6000);// 设置超时时间为6000毫秒，conn.setConnectionTiem(0);表示没有时间限制
            conn.setDoInput(true);// 连接设置获得数据流
            conn.setUseCaches(false);// 不使用缓存
            InputStream is = conn.getInputStream();// 得到数据流，这里会有调用conn.connect();

            // 解析得到图片
            bitmap = decodeStreamToBitmap(is, null, null);
            is.close();// 关闭数据流
        } catch (Exception e) {
            e.printStackTrace();
        }

        return bitmap;
    }

    /**
     * 从资源中获取Bitmap
     *
     * @param context
     * @param resid   例如这样：ResourceTable.Media_icon
     * @return
     */
    public static PixelMap getBitmapFromResources(Context context, int resid) {
        String path = null;
        try {
            path = context.getResourceManager().getMediaPath(resid);
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }
        if(path!=null) {
            return ImageSource.create(path, null).createPixelmap(null);
        }
        return null;
    }

    /**
     * Bitmap转字节
     *
     * @param bitmap
     * @return
     */
    public byte[] Bitmap2Bytes(PixelMap bitmap) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        compressImageToStream(bitmap, "image/png", 100, baos);
        return baos.toByteArray();
    }

    /**
     * 字节转Bitmap
     *
     * @param bytes
     * @return
     */
    public PixelMap Bytes2Bimap(byte[] bytes) {
        if (bytes.length != 0) {
            ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
            return decodeStreamToBitmap(stream, null, null);
        } else {
            return null;
        }
    }

    /**
     * Bitmap缩放，可能比例要注意一下
     *
     * @param bitmap
     * @param width
     * @param height
     * @return
     */
    public static PixelMap zoomBitmap(PixelMap bitmap, int width, int height) {
        int w = bitmap.getImageInfo().size.width;
        int h = bitmap.getImageInfo().size.height;
        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.pixelFormat = PixelFormat.ARGB_8888;
        options.scaleMode = ScaleMode.FIT_TARGET_SIZE;
        options.size = new Size(width, height);
        PixelMap newbmp = PixelMap.create(bitmap, new ohos.media.image.common.Rect(0, 0, w, h), options);
        return newbmp;
    }

    /**
     * 将Drawable转化为Bitmap
     *
     * @param drawable
     * @return
     */
    public static PixelMap drawable2Bitmap(Element drawable) {
        // 取 drawable 的长宽
        int w = drawable.getWidth();
        int h = drawable.getHeight();

        // 取 drawable 的颜色格式
        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.pixelFormat = drawable.getAlpha() != 0xff ? PixelFormat.ARGB_8888 : PixelFormat.RGB_565;
        options.size = new Size(w, h);
        options.alphaType = drawable.getAlpha() != 0xff ? AlphaType.UNKNOWN : AlphaType.OPAQUE;
        options.editable = true;

        // 建立对应 bitmap
        PixelMap bitmap = PixelMap.create(options);

        // 建立对应 bitmap 的画布
        Canvas canvas = new Canvas(new Texture(bitmap));
        drawable.setBounds(0, 0, w, h);

        // 把 drawable 内容画到画布中
        drawable.drawToCanvas(canvas);
        return bitmap;
    }

    /**
     * Bitmap转换成Drawable
     *
     * @param context
     * @param bitmap
     * @return
     */
    public static Element Bitmap2Drawable(Context context, PixelMap bitmap) {
        return new PixelMapElement(bitmap);
    }

    /**
     * 获得圆角图片
     *
     * @param bitmap
     * @param roundPx
     * @return
     */
    public static PixelMap getRoundedCornerBitmap(PixelMap bitmap, float roundPx) {
        int w = bitmap.getImageInfo().size.width;
        int h = bitmap.getImageInfo().size.height;

        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.pixelFormat = PixelFormat.ARGB_8888;
        options.size = new Size(w, h);
        options.editable = true;

        PixelMap output = PixelMap.create(options);
        Canvas canvas = new Canvas(new Texture(output));
        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, w, h);
        final RectFloat rectF = new RectFloat(rect);
        paint.setAntiAlias(true);
        canvas.drawColor(Color.BLACK.getValue(), BlendMode.CLEAR);
        canvas.drawPixelMapHolderRoundRectShape(new PixelMapHolder(bitmap), rectF, rectF, roundPx, roundPx);
        return output;
    }


    public static class ImagePiece {
        public PixelMap bitmap = null;
        public int index = 0;

        public ImagePiece(PixelMap bitmap) {
            this.bitmap = bitmap;
            this.index = 0;
        }

        public ImagePiece(PixelMap bitmap, int index) {
            this.bitmap = bitmap;
            this.index = index;
        }
    }


    /**
     * 制作圆形图片
     *
     * @param rect
     */
    public static PixelMap rectBitmapToCircle(PixelMap rect) {
        Shader mBitmapShader = new PixelMapShader(new PixelMapHolder(rect), Shader.TileMode.CLAMP_TILEMODE,
                Shader.TileMode.CLAMP_TILEMODE);
        Paint paint = new Paint();
        paint.setShader(mBitmapShader, Paint.ShaderType.PIXELMAP_SHADER);

        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.pixelFormat = PixelFormat.ARGB_8888;
        options.size = rect.getImageInfo().size;
        options.editable = true;

        PixelMap output = PixelMap.create(options);
        Canvas canvas = new Canvas(new Texture(output));
        canvas.drawCircle(rect.getImageInfo().size.width / 2f,
                rect.getImageInfo().size.height / 2f,
                Math.min(rect.getImageInfo().size.width, rect.getImageInfo().size.height) / 2f
                , paint);
        return output;
    }
}
